package jp.co.ikd.swing.compornent;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import javax.swing.text.StyleConstants;

public class IkdDocument extends PlainDocument {

	private static final long serialVersionUID = 1L;

	private InputCharType inputCharType;

	/** 最大文字数 */
	private int maxLength = -1;

	private UpperStringType upperStringType;

	/**
	 * フィールドに文字列が挿入される際に呼び出される挿入処理です。
	 * <p>
	 * 入力された文字種を判断して、数字のみを挿入します。
	 * <p>
	 *
	 * @param offs オフセット(挿入開始位置)
	 * @param str 挿入文字列
	 * @param a AttributeSet（文字の属性）
	 * @exception BadLocationException
	 */
	public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {

		if (str == null)
			return;

		// IMEの変換中の文字列はそのままinsertする
		if ((a != null) && (a.isDefined(StyleConstants.ComposedTextAttribute))) {
			super.insertString(offs, str, a);
			return;
		}

		// 実際に挿入をするオフセット
		int realOffs = offs;

		// 入力文字列を一文字ずつ判定
		for (int i = 0; i < str.length(); i++) {

			// 制限文字数となったら、挿入をやめる
			if (this.maxLength >= 0 && getLength() >= this.maxLength) {
				break;
			}

			char c = str.charAt(i);

			// 文字種として正しい場合、挿入を行う
			if (checkChar(c)) {

				String s = String.valueOf(c);

				// 大文字・小文字の変換
				if (upperStringType != null) {
					switch (upperStringType) {
					case TO_UPPER:
						s = s.toUpperCase();
						break;
					case TO_LOWER:
						s = s.toLowerCase();
						break;
					default:
						break;
					}
				}

				super.insertString(realOffs, s, a);
				realOffs++;
			} else {
				break;
			}
		}
	}

	public void setUpperStringType(UpperStringType upperStringType) {
		this.upperStringType = upperStringType;

	}

	public void setInputType(InputCharType inputType) {
		this.inputCharType = inputType;
	}

	public void setMaxLength(int maxLength) {
		this.maxLength = maxLength;
	}

	/**
	 * 文字種チェック
	 * <p>
	 * 半角数字,半角英数,半角英数記号<BR>
	 * ※パターンが物足りない場合は追加していく。
	 * </p>
	 * @param c 対象の文字
	 * @return 文字種正誤
	 */
	private boolean checkChar(char c) {

		if (this.inputCharType == null) {
			return true;
		}

		switch (this.inputCharType) {
		case HALF_NUMBER: // [0-9]
			if (0x0030 <= c && c <= 0x0039) {
				return true;
			}
			break;
		case HALF_ALPA: // [a-zA-Z]
			if ((0x0041 <= c && c <= 0x005A) || (0x0061 <= c && c <= 0x007A)) {
				return true;
			}
			break;
		case HALF_ALPA_NUMER:// [0-9a-zA-Z]
			if ((0x0030 <= c && c <= 0x0039) || (0x0041 <= c && c <= 0x005A) || (0x0061 <= c && c <= 0x007A)) {
				return true;
			}
			break;
		case HALF: // '{','|','}' ,'~'は除いてみた
			if (0x0020 <= c && c <= 0x007A) {
				return true;
			}
			break;
		default:
			break;
		}
		return false;
	}
}